"""
智能剧场生成器 - 完整版
支持智能生成向导和实时进度跟踪
单一对话上下文确保内容一致性
包含技能数据标准化处理
"""

import os
import json
import re
import requests
import asyncio
import uuid
from typing import Dict, List, Any, Optional
from dataclasses import dataclass, asdict
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
from enum import Enum
from database import get_mysql_manager
from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
import uvicorn

# ==================== 枚举和常量 ====================

class GenerationStage(str, Enum):
    ANALYSIS = "analysis"
    CONCEPT = "concept"
    STRUCTURE = "structure"
    CHARACTERS = "characters"
    SKILLS = "skills"
    PLOT = "plot"
    OPTIMIZATION = "optimization"
    COMPLETE = "complete"

class TaskStatus(str, Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"

# ==================== 数据模型 ====================

@dataclass
class ScriptNode:
    id: str
    title: str
    content: str
    characterSettings: Dict[str, Any]
    level: int

@dataclass
class Character:
    id: str
    name: str
    description: str
    avatar: str
    selectedSkills: List[str]

@dataclass
class TheaterData:
    title: str
    description: str
    era: str
    location: str
    createdAt: str
    author: str
    plotSummary: str
    features: List[str]

@dataclass
class GenerationProgress:
    task_id: str
    status: TaskStatus
    progress: float
    current_stage: GenerationStage
    message: str
    result: Optional[Dict[str, Any]] = None
    error: Optional[str] = None
    created_at: Optional[datetime] = None

# ==================== API请求模型 ====================

class IntelligentGenerationRequest(BaseModel):
    """智能生成请求"""
    user_input: str = Field(..., description="用户描述的剧场需求")
    complexity_level: str = Field("medium", description="复杂度：simple, medium, complex")
    target_audience: str = Field("general", description="目标观众：general, young, mature, family")
    special_requirements: List[str] = Field(default=[], description="特殊要求列表")

class ApiResponse(BaseModel):
    success: bool
    message: str
    data: Optional[Dict[str, Any]] = None
    error_code: Optional[str] = None
    task_id: Optional[str] = None

# ==================== 全局进度跟踪 ====================

# 存储生成任务的进度
generation_tasks: Dict[str, GenerationProgress] = {}

# ==================== AI生成器类 ====================

class IntelligentTheaterGenerator:
    def __init__(self):
        self.api_key = os.getenv('GEEKAI_API_KEY')
        if not self.api_key:
            raise ValueError("请设置GEEKAI_API_KEY环境变量")
        
        self.base_url = 'https://geekai.co/api/v1/chat/completions'
        self.headers = {
            'Authorization': f'Bearer {self.api_key}',
            'Content-Type': 'application/json'
        }
        
        # 为每个生成任务维护独立的对话历史
        self.conversation_histories: Dict[str, List[Dict]] = {}
        self.mysql_manager = get_mysql_manager()
    def initialize_conversation(self, task_id: str, request: IntelligentGenerationRequest):
        """初始化剧场生成的对话上下文"""
        system_prompt = f"""
        你是一位顶级的互动剧场创作大师，负责为用户创作一个完整的沉浸式剧场体验。

        用户需求：
        - 剧场描述：{request.user_input}
        - 复杂度级别：{request.complexity_level}
        - 目标观众：{request.target_audience}
        - 特殊要求：{', '.join(request.special_requirements) if request.special_requirements else '无'}

        你的任务是逐步创作这个剧场，包括：
        1. 分析需求并确定剧场的核心概念
        2. 设计剧场的基本信息和世界观
        3. 构建故事结构和幕次安排
        4. 创造生动的角色形象
        5. 设计技能体系
        6. 逐个编写每个场景的详细内容

        在整个创作过程中，请保持：
        - 风格和语调的一致性
        - 角色性格和行为的连贯性
        - 剧情逻辑的合理性
        - 世界观设定的统一性

        每一步都要基于前面已经确立的内容进行创作，确保整个剧场是一个有机的整体。
        
        请始终以JSON格式返回结构化数据，确保格式正确。
        """
        
        self.conversation_histories[task_id] = [
            {"role": "system", "content": system_prompt}
        ]

    async def call_ai_with_context(self, task_id: str, user_message: str, temperature: float = 0.8) -> str:
        """在对话上下文中调用AI API"""
        if task_id not in self.conversation_histories:
            raise Exception(f"任务 {task_id} 的对话上下文不存在")
        
        # 添加用户消息到对话历史
        self.conversation_histories[task_id].append({
            "role": "user", 
            "content": user_message
        })
        
        payload = {
            "model": "gpt-4o-mini",
            "messages": self.conversation_histories[task_id],
            "temperature": temperature,
            "max_tokens": 2000
        }
        
        loop = asyncio.get_event_loop()
        
        def sync_call():
            try:
                response = requests.post(
                    self.base_url,
                    headers=self.headers,
                    json=payload,
                    timeout=600
                )
                response.raise_for_status()
                result = response.json()
                return result['choices'][0]['message']['content']
            except Exception as e:
                raise Exception(f"AI API调用失败: {e}")
        
        with ThreadPoolExecutor() as executor:
            ai_response = await loop.run_in_executor(executor, sync_call)
        
        # 将AI回复添加到对话历史
        self.conversation_histories[task_id].append({
            "role": "assistant",
            "content": ai_response
        })
        
        return ai_response

    def update_progress(self, task_id: str, stage: GenerationStage, progress: float, message: str):
        """更新生成进度"""
        if task_id in generation_tasks:
            generation_tasks[task_id].current_stage = stage
            generation_tasks[task_id].progress = progress
            generation_tasks[task_id].message = message
            generation_tasks[task_id].status = TaskStatus.RUNNING

    def normalize_skills_data(self, raw_skills: List[Any]) -> List[str]:
        """🔧 标准化技能数据格式 - 方案三的核心实现"""
        normalized_skills = []
        
        print(f"🔧 开始标准化技能数据，原始数据类型: {type(raw_skills)}")
        print(f"🔧 原始技能数据: {raw_skills}")
        
        for i, skill in enumerate(raw_skills):
            try:
                if isinstance(skill, str):
                    # 标准情况：直接是字符串
                    normalized_skills.append(skill.strip())
                    print(f"✅ 技能 {i+1}: 字符串格式 - '{skill.strip()}'")
                    
                elif isinstance(skill, dict):
                    if 'skills' in skill and isinstance(skill['skills'], list):
                        # 处理分类格式：{"category": "类别", "skills": ["技能1", "技能2"]}
                        category_skills = skill['skills']
                        normalized_skills.extend([s.strip() for s in category_skills if isinstance(s, str)])
                        print(f"✅ 技能 {i+1}: 分类格式 - 提取了 {len(category_skills)} 个技能")
                        
                    elif 'name' in skill:
                        # 处理详细格式：{"name": "技能名", "description": "描述"}
                        skill_name = skill['name'].strip()
                        normalized_skills.append(skill_name)
                        print(f"✅ 技能 {i+1}: 详细格式 - '{skill_name}'")
                        
                    elif 'skill' in skill:
                        # 处理另一种格式：{"skill": "技能名"}
                        skill_name = skill['skill'].strip()
                        normalized_skills.append(skill_name)
                        print(f"✅ 技能 {i+1}: 简化格式 - '{skill_name}'")
                        
                    else:
                        # 其他对象格式，尝试转换为字符串
                        skill_str = str(skill)
                        # 如果看起来像JSON，试图解析它
                        if skill_str.startswith('{') and skill_str.endswith('}'):
                            try:
                                skill_obj = json.loads(skill_str)
                                if isinstance(skill_obj, dict) and 'skills' in skill_obj:
                                    normalized_skills.extend(skill_obj['skills'])
                                    print(f"✅ 技能 {i+1}: JSON字符串格式 - 解析成功")
                                else:
                                    normalized_skills.append(skill_str)
                                    print(f"⚠️ 技能 {i+1}: 未知对象格式，转为字符串 - '{skill_str[:50]}...'")
                            except:
                                normalized_skills.append(skill_str)
                                print(f"⚠️ 技能 {i+1}: JSON解析失败，转为字符串 - '{skill_str[:50]}...'")
                        else:
                            normalized_skills.append(skill_str)
                            print(f"⚠️ 技能 {i+1}: 对象转字符串 - '{skill_str[:50]}...'")
                            
                elif isinstance(skill, list):
                    # 处理嵌套列表
                    flattened = self.normalize_skills_data(skill)
                    normalized_skills.extend(flattened)
                    print(f"✅ 技能 {i+1}: 嵌套列表格式 - 展开了 {len(flattened)} 个技能")
                    
                else:
                    # 其他类型，直接转换为字符串
                    skill_str = str(skill).strip()
                    if skill_str:  # 只添加非空字符串
                        normalized_skills.append(skill_str)
                        print(f"⚠️ 技能 {i+1}: 其他类型转字符串 - '{skill_str}'")
                        
            except Exception as e:
                print(f"❌ 技能 {i+1} 处理失败: {e}, 原始数据: {skill}")
                # 最后的兜底方案
                try:
                    fallback_str = str(skill).strip()
                    if fallback_str and fallback_str != 'None':
                        normalized_skills.append(fallback_str)
                        print(f"🔄 技能 {i+1}: 兜底处理 - '{fallback_str}'")
                except:
                    print(f"💥 技能 {i+1}: 完全无法处理，跳过")
                    continue
        
        # 去重和清理
        unique_skills = []
        seen = set()
        for skill in normalized_skills:
            skill_clean = skill.strip()
            if skill_clean and skill_clean not in seen and len(skill_clean) > 1:
                unique_skills.append(skill_clean)
                seen.add(skill_clean)
        
        print(f"🎯 标准化完成: 原始 {len(raw_skills)} 项 → 处理后 {len(normalized_skills)} 项 → 去重后 {len(unique_skills)} 项")
        print(f"🎯 最终技能列表: {unique_skills}")
        
        return unique_skills

    async def analyze_user_requirements(self, task_id: str, request: IntelligentGenerationRequest) -> Dict:
        """第一步：分析用户需求"""
        self.update_progress(task_id, GenerationStage.ANALYSIS, 10, "正在分析您的需求描述...")
        
        prompt = """
        首先，请分析我提供的剧场需求，提取出关键信息。

        请以JSON格式返回分析结果：
        {
            "theme": "主题",
            "genre": "类型（fantasy/sci-fi/romance/thriller/comedy）",
            "setting": "背景设定",
            "tone": "整体基调",
            "key_elements": ["关键要素1", "关键要素2"],
            "suggested_characters": ["建议角色类型1", "建议角色类型2"],
            "estimated_acts": 3,
            "estimated_duration": 30
        }

        分析完成后，请确认这个方向是否符合用户的期望。
        """
        
        response = await self.call_ai_with_context(task_id, prompt, temperature=0.7)
        json_match = re.search(r'\{.*\}', response, re.DOTALL)
        if json_match:
            return json.loads(json_match.group())
        else:
            raise Exception("需求分析失败")

    async def generate_theater_concept(self, task_id: str, analysis: Dict) -> TheaterData:
        """第二步：生成剧场概念"""
        self.update_progress(task_id, GenerationStage.CONCEPT, 25, "正在构建剧场概念...")
        
        prompt = f"""
        很好！基于刚才的需求分析，现在请为这个剧场设计详细的概念信息。

        已确定的核心方向：
        - 主题：{analysis.get('theme', '')}
        - 类型：{analysis.get('genre', '')}
        - 背景设定：{analysis.get('setting', '')}

        请设计剧场的完整概念，以JSON格式返回：
        {{
            "title": "剧场标题",
            "description": "剧场描述（100-150字）",
            "era": "时代背景",
            "location": "故事地点",
            "plotSummary": "情节摘要（200-300字）",
            "features": ["特色1", "特色2", "特色3", "特色4", "特色5"]
        }}

        请确保这个概念与前面分析的方向完全一致。
        """
        
        response = await self.call_ai_with_context(task_id, prompt, temperature=0.8)
        json_match = re.search(r'\{.*\}', response, re.DOTALL)
        if json_match:
            data = json.loads(json_match.group())
            return TheaterData(
                title=data.get('title', '智能生成剧场'),
                description=data.get('description', ''),
                era=data.get('era', ''),
                location=data.get('location', ''),
                createdAt=datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                author='AI智能生成器',
                plotSummary=data.get('plotSummary', ''),
                features=data.get('features', [])
            )
        else:
            raise Exception("剧场概念生成失败")

    async def generate_story_structure(self, task_id: str, analysis: Dict, theater_data: TheaterData) -> List[Dict]:
        """第三步：生成故事结构"""
        self.update_progress(task_id, GenerationStage.STRUCTURE, 40, "正在设计故事结构...")
        
        num_acts = analysis.get('estimated_acts', 3)
        
        prompt = f"""
        接下来，请为剧场《{theater_data.title}》设计{num_acts}幕的详细故事结构。

        已确定的剧场信息：
        - 标题：{theater_data.title}
        - 描述：{theater_data.description}
        - 时代背景：{theater_data.era}
        - 故事地点：{theater_data.location}
        - 情节摘要：{theater_data.plotSummary}

        请为每一幕设计3-5个场景，确保故事结构紧凑且富有戏剧张力。以JSON格式返回：
        {{
            "acts": [
                {{
                    "act_number": 1,
                    "title": "第一幕标题",
                    "theme": "本幕主题",
                    "scenes": [
                        {{
                            "title": "场景标题",
                            "description": "场景描述",
                            "key_events": ["关键事件1", "关键事件2"],
                            "mood": "场景氛围"
                        }}
                    ]
                }}
            ]
        }}

        故事结构要与前面设定的剧场概念完美呼应。
        """
        
        response = await self.call_ai_with_context(task_id, prompt, temperature=0.7)
        json_match = re.search(r'\{.*\}', response, re.DOTALL)
        if json_match:
            return json.loads(json_match.group())['acts']
        else:
            raise Exception("故事结构生成失败")

    async def generate_characters(self, task_id: str, analysis: Dict, theater_data: TheaterData) -> List[Character]:
        """第四步：生成角色"""
        self.update_progress(task_id, GenerationStage.CHARACTERS, 55, "正在设计角色...")
        
        prompt = f"""
        现在请为剧场《{theater_data.title}》设计主要角色。

        基于已经确定的：
        - 剧场背景：{theater_data.era} - {theater_data.location}
        - 剧场主题：{analysis.get('theme', '')}
        - 故事类型：{analysis.get('genre', '')}
        - 建议角色类型：{', '.join(analysis.get('suggested_characters', []))}

        请设计3-5个主要角色，每个角色都要与剧场的世界观和故事完美融合。以JSON格式返回：
        {{
            "characters": [
                {{
                    "name": "角色名称",
                    "description": "角色描述（120-150字，包含背景、性格、动机）",
                    "personality": "核心性格特点",
                    "role_type": "角色定位（主角/重要配角/关键NPC等）",
                    "background": "角色背景故事",
                    "motivation": "角色的核心动机"
                }}
            ]
        }}

        确保角色之间有合理的关系网络，能够推动剧情发展。
        """
        
        response = await self.call_ai_with_context(task_id, prompt, temperature=0.8)
        json_match = re.search(r'\{.*\}', response, re.DOTALL)
        if json_match:
            chars_data = json.loads(json_match.group())['characters']
            characters = []

            print(f"🔍 AI返回的角色数据: {len(chars_data)} 个角色")

            for i, char_data in enumerate(chars_data):
                print(f"🔍 处理角色 {i+1}: {char_data.get('name', 'Unknown')}")

                character = Character(
                    id=f"char-{i+1}",
                    name=char_data.get('name', f'角色{i+1}'),
                    description=char_data.get('description', ''),
                    avatar=f"https://ui-avatars.com/api/?name={char_data.get('name', f'角色{i+1}')}&background=random&color=fff",
                    selectedSkills=[]  # 🔧 确保是空列表，稍后分配技能
                )
                characters.append(character)
                print(f"✅ 角色对象创建完成: {character.name}")

            return characters
        else:
            raise Exception("角色生成失败")

    async def generate_skills(self, task_id: str, analysis: Dict, characters: List[Character]) -> List[str]:
        """第五步：生成技能池 - 🔧 包含数据标准化处理"""
        self.update_progress(task_id, GenerationStage.SKILLS, 70, "正在生成技能体系...")
        
        char_info = [f"- {char.name}: {char.description[:80]}..." for char in characters]
        
        prompt = f"""
        现在请为这个剧场设计完整的技能体系。

        基于已设计的角色：
        {chr(10).join(char_info)}

        以及剧场的类型和主题，请设计25-30个技能，要确保：
        1. 技能与剧场的世界观设定相符
        2. 涵盖不同的使用场景
        3. 角色能够合理地拥有这些技能

        ⚠️ 重要：请严格按照以下JSON格式返回，skills字段必须是简单的字符串数组：
        {{
            "skills": [
                "技能名称1",
                "技能名称2", 
                "技能名称3",
                "剑术精通",
                "魔法感知",
                "谈判技巧"
            ]
        }}

        ❌ 错误格式示例（不要返回这种格式）：
        {{
            "skills": [
                {{"category": "战斗类", "skills": ["剑术", "格斗"]}},
                {{"name": "魔法", "description": "施展魔法"}}
            ]
        }}

        ✅ 正确格式：每个技能都是一个独立的字符串，不要分类或嵌套。

        技能分类建议：
        - 战斗类技能（如果剧情涉及冲突）
        - 社交类技能（对话和交互）
        - 智力类技能（解谜和分析）
        - 生存类技能（应对环境挑战）
        - 特殊类技能（符合剧场独特设定的技能）
        
        请直接列出技能名称，不要包含分类信息。
        """
        
        response = await self.call_ai_with_context(task_id, prompt, temperature=0.7)
        
        try:
            json_match = re.search(r'\{.*\}', response, re.DOTALL)
            if json_match:
                data = json.loads(json_match.group())
                raw_skills = data.get('skills', [])
                
                print(f"🔧 AI原始返回的技能数据: {raw_skills}")
                
                # 🔧 使用标准化函数处理技能数据
                normalized_skills = self.normalize_skills_data(raw_skills)
                
                # 确保至少有一些技能
                if len(normalized_skills) < 10:
                    print(f"⚠️ 技能数量不足 ({len(normalized_skills)})，添加默认技能")
                    default_skills = [
                        "观察力", "交流能力", "逻辑思维", "创造力", "领导力",
                        "团队合作", "适应能力", "解决问题", "时间管理", "情绪控制"
                    ]
                    for skill in default_skills:
                        if skill not in normalized_skills:
                            normalized_skills.append(skill)
                            if len(normalized_skills) >= 15:
                                break
                
                print(f"✅ 最终标准化的技能列表: {normalized_skills}")
                return normalized_skills
                
            else:
                raise Exception("AI返回格式不正确，未找到JSON结构")
                
        except json.JSONDecodeError as e:
            print(f"❌ JSON解析失败: {e}")
            print(f"原始响应: {response}")
            raise Exception(f"技能生成失败 - JSON解析错误: {e}")
        except Exception as e:
            print(f"❌ 技能生成过程出错: {e}")
            # 返回默认技能作为兜底
            default_skills = [
                "基础交流", "观察分析", "逻辑推理", "创意思维", "团队协作",
                "问题解决", "适应变化", "时间规划", "情绪管理", "学习能力",
                "领导组织", "谈判协商", "资源管理", "风险评估", "决策制定"
            ]
            print(f"🔄 使用默认技能兜底: {default_skills}")
            return default_skills

    async def generate_detailed_plot(self, task_id: str, story_structure: List[Dict], 
                                   characters: List[Character], theater_data: TheaterData) -> List[ScriptNode]:
        """第六步：逐个生成详细剧情节点（在同一对话中）"""
        self.update_progress(task_id, GenerationStage.PLOT, 85, "开始编写详细剧情...")
        
        script_nodes = []
        node_counter = 1
        
        # 计算总场景数
        total_scenes = sum(len(act['scenes']) for act in story_structure)
        
        # 先向AI介绍即将开始的剧情创作任务
        intro_prompt = f"""
        太好了！现在我们已经完成了剧场的基础设计：

        📋 剧场概况：
        - 标题：{theater_data.title}
        - 类型：{theater_data.description}
        - 角色：{', '.join([char.name for char in characters])}
        - 总场景数：{total_scenes}个

        🎬 故事结构：
        {chr(10).join([f"第{act['act_number']}幕《{act['title']}》: {len(act['scenes'])}个场景" for act in story_structure])}

        接下来，我们要逐个编写每个场景的详细内容。我会按顺序给你每个场景的基本信息，请你基于前面确立的所有设定来创作详细的场景内容。

        重要：每个场景都要与前面的剧情保持连贯，角色的行为要符合他们的性格设定，整体风格要保持一致。

        准备好了吗？让我们开始创作第一个场景！
        """
        
        await self.call_ai_with_context(task_id, intro_prompt, temperature=0.7)
        
        # 逐个生成每个场景
        for act_index, act in enumerate(story_structure):
            for scene_index, scene in enumerate(act['scenes']):
                current_scene_num = len(script_nodes) + 1
                
                # 更新进度
                base_progress = 85
                scene_progress = (current_scene_num - 1) / total_scenes * 10
                current_progress = base_progress + scene_progress
                
                self.update_progress(
                    task_id, 
                    GenerationStage.PLOT, 
                    current_progress, 
                    f"正在创作第 {current_scene_num}/{total_scenes} 个场景: {scene['title']}"
                )
                
                try:
                    # 在对话上下文中生成场景
                    script_node = await self.generate_scene_in_context(
                        task_id, scene, act, current_scene_num, total_scenes, 
                        node_counter, characters, theater_data
                    )
                    script_nodes.append(script_node)
                    
                    # 更新完成进度
                    completed_progress = 85 + (current_scene_num / total_scenes * 10)
                    self.update_progress(
                        task_id, 
                        GenerationStage.PLOT, 
                        completed_progress,
                        f"✅ 场景 '{scene['title']}' 创作完成 ({current_scene_num}/{total_scenes})"
                    )
                    
                    # 短暂延迟
                    await asyncio.sleep(0.3)
                    
                except Exception as e:
                    print(f"❌ 场景 '{scene['title']}' 生成失败: {e}")
                    # 创建备用场景
                    fallback_node = self.create_fallback_scene_node(scene, node_counter, characters)
                    script_nodes.append(fallback_node)
                
                node_counter += 1
        
        self.update_progress(task_id, GenerationStage.PLOT, 95, f"所有 {len(script_nodes)} 个场景创作完成！")
        return script_nodes

    async def generate_scene_in_context(self, task_id: str, scene: Dict, act: Dict, 
                                      current_scene_num: int, total_scenes: int,
                                      node_counter: int, characters: List[Character], 
                                      theater_data: TheaterData) -> ScriptNode:
        """在对话上下文中生成单个场景"""
        
        character_names = [char.name for char in characters]
        
        prompt = f"""
        【第 {current_scene_num}/{total_scenes} 个场景】

        🎭 所属幕次：{act['title']} ({act.get('theme', '')})
        📝 场景标题：{scene['title']}
        📖 场景描述：{scene['description']}
        🎯 关键事件：{', '.join(scene.get('key_events', []))}
        🎨 场景氛围：{scene.get('mood', '待定')}

        👥 可用角色：{', '.join(character_names)}

        请为这个场景创作详细内容，要求：
        1. 内容丰富生动，400-600字
        2. 使用HTML标签格式化（<p>、<strong>、<em>、<br>等）
        3. 与前面的剧情和角色设定保持完全一致
        4. 推进整体故事发展
        5. 为玩家提供有意义的选择和参与机会

        以JSON格式返回：
        {{
            "title": "场景标题",
            "content": "HTML格式的详细场景内容"
        }}
        """
        
        response = await self.call_ai_with_context(task_id, prompt, temperature=0.8)
        
        # 解析响应
        json_match = re.search(r'\{.*\}', response, re.DOTALL)
        if not json_match:
            raise Exception("场景内容格式无效")
        
        scene_data = json.loads(json_match.group())
        
        # 创建角色设置
        character_settings = self.create_character_settings_for_scene(characters, scene)
        
        return ScriptNode(
            id=f"node-{node_counter}",
            title=scene_data.get('title', scene['title']),
            content=scene_data.get('content', f'<p><strong>{scene["title"]}</strong></p><p>{scene["description"]}</p>'),
            characterSettings=character_settings,
            level=0
        )

    def create_character_settings_for_scene(self, characters: List[Character], scene: Dict) -> Dict:
        """为场景创建角色设置"""
        character_settings = {}
        
        for char in characters:
            character_settings[char.id] = {
                "behaviors": [
                    f"以{char.name}的性格方式观察环境",
                    f"根据{char.name}的背景做出反应",
                    "与其他角色进行符合身份的互动"
                ],
                "conditions": [
                    {
                        "type": "success", 
                        "description": f"{char.name}成功推进剧情",
                        "effects": ["获得经验", "加深关系", "推动故事发展"]
                    },
                    {
                        "type": "failure", 
                        "description": f"{char.name}遇到挫折",
                        "effects": ["面临困难", "需要帮助", "寻找新方法"]
                    },
                    {
                        "type": "critical", 
                        "description": f"{char.name}发挥关键作用",
                        "effects": ["剧情转折", "角色成长", "获得重要信息"]
                    }
                ],
                "branches": [
                    {"name": "主动行动", "description": f"{char.name}主动采取行动"},
                    {"name": "谨慎应对", "description": f"{char.name}谨慎观察后决定"},
                    {"name": "寻求合作", "description": f"{char.name}寻找其他角色的帮助"},
                    {"name": "独立思考", "description": f"{char.name}依靠自己的判断"}
                ]
            }
        
        return character_settings

    def create_fallback_scene_node(self, scene: Dict, node_counter: int, characters: List[Character]) -> ScriptNode:
        """创建备用场景节点（当AI生成失败时使用）"""
        
        # 生成基础HTML内容
        fallback_content = f"""
        <div class="scene-content">
            <h3>{scene['title']}</h3>
            <p><strong>场景描述：</strong>{scene['description']}</p>
            
            {f'<p><strong>关键事件：</strong></p><ul>{"".join([f"<li>{event}</li>" for event in scene.get("key_events", [])])}</ul>' if scene.get("key_events") else ''}
            
            <p><em>这是一个重要的剧情节点，需要您的参与和选择来推进故事发展...</em></p>
            
            <p>💭 <strong>思考时刻：</strong>在这个情况下，您会如何应对？</p>
        </div>
        """
        
        # 创建简化的角色设置
        character_settings = {}
        for char in characters:
            character_settings[char.id] = {
                "behaviors": ["等待用户指示", "观察情况发展"],
                "conditions": [
                    {"type": "default", "description": "标准剧情发展"}
                ],
                "branches": [
                    {"name": "继续前进"},
                    {"name": "暂停思考"}
                ]
            }
        
        return ScriptNode(
            id=f"node-{node_counter}",
            title=scene['title'],
            content=fallback_content,
            characterSettings=character_settings,
            level=0
        )

    async def finalize_generation(self, task_id: str, theater_data: TheaterData, 
                                 script_nodes: List[ScriptNode], characters: List[Character], 
                                 skills: List[str]) -> Dict[str, Any]:
        """第七步：最终优化"""
        self.update_progress(task_id, GenerationStage.OPTIMIZATION, 98, "正在进行最终优化...")
        
        # 为角色分配技能
        skills_per_character = min(5, len(skills) // len(characters)) if characters else 0
        for i, character in enumerate(characters):
            start_idx = i * skills_per_character
            end_idx = start_idx + skills_per_character
            character.selectedSkills = skills[start_idx:end_idx] if end_idx <= len(skills) else skills[start_idx:]
        
        # 组装最终结果
        result = {
            "theater_info": asdict(theater_data),
            "script_nodes": [asdict(node) for node in script_nodes],
            "characters": [asdict(char) for char in characters],
            "available_skills": skills
        }
        # 🚀 异步保存到
        await self._save_to_theater_data_async(task_id, result, theater_data.title)
        self.update_progress(task_id, GenerationStage.COMPLETE, 100, "生成完成！")
        return result

    async def _save_to_theater_data_async(self, task_id: str, result: Dict[str, Any], title: str):
        """异步保存数据到MySQL数据库"""
        try:
            self.update_progress(task_id, GenerationStage.OPTIMIZATION, 99, "正在保存到数据库...")

            print(f"🚀 开始异步保存剧场到MySQL: {title}")

            # 使用MySQL管理器保存数据
            save_result = await self.mysql_manager.save_theater_data_async(task_id, result)

            if save_result and save_result.get('success'):
                # 保存成功
                theater_id = save_result.get('theater_id')
                result["mysql_save_result"] = save_result
                result["mysql_theater_id"] = theater_id

                print(f"🎉 剧场保存到MySQL成功!")
                print(f"   📝 剧场标题: {title}")
                print(f"   🆔 MySQL ID: {theater_id}")
                print(f"   📊 节点数量: {len(result.get('script_nodes', []))}")
                print(f"   👥 角色数量: {len(result.get('characters', []))}")
                print(f"   ⚔️ 技能数量: {len(result.get('available_skills', []))}")
                print(f"   ⏱️ 保存耗时: {save_result.get('duration_seconds', 0):.2f}秒")

                # 更新任务进度信息
                generation_tasks[task_id].message = f"生成完成！已保存到MySQL数据库 (ID: {theater_id})"

            else:
                # 保存失败
                error_msg = save_result.get('error', '未知错误') if save_result else 'MySQL保存服务未响应'
                print(f"⚠️ MySQL保存失败: {error_msg}")

                result["mysql_save_result"] = save_result
                result["mysql_save_error"] = error_msg

                generation_tasks[task_id].message = f"生成完成！(MySQL保存失败: {error_msg})"

        except Exception as e:
            error_msg = f"MySQL保存过程异常: {str(e)}"
            print(f"❌ MySQL保存异常: {error_msg}")

            result["mysql_save_error"] = error_msg
            generation_tasks[task_id].message = f"生成完成！(MySQL保存异常: {error_msg})"
    async def generate_intelligent_theater(self, task_id: str, request: IntelligentGenerationRequest):
        """智能生成完整剧场 - 单一对话上下文版本"""
        try:
            print(f"🎭 开始智能生成任务: {task_id}")
            
            # 初始化对话上下文
            self.initialize_conversation(task_id, request)
            
            # 第一步：分析用户需求
            analysis = await self.analyze_user_requirements(task_id, request)
            print(f"✅ 需求分析完成: {analysis.get('theme', 'N/A')}")
            
            # 第二步：生成剧场概念
            theater_data = await self.generate_theater_concept(task_id, analysis)
            print(f"✅ 剧场概念完成: {theater_data.title}")
            
            # 第三步：生成故事结构
            story_structure = await self.generate_story_structure(task_id, analysis, theater_data)
            total_scenes = sum(len(act['scenes']) for act in story_structure)
            print(f"✅ 故事结构完成: {len(story_structure)}幕, {total_scenes}个场景")
            
            # 第四步：生成角色
            characters = await self.generate_characters(task_id, analysis, theater_data)
            print(f"✅ 角色设计完成: {len(characters)}个角色")
            
            # 第五步：生成技能池（包含数据标准化）
            skills = await self.generate_skills(task_id, analysis, characters)
            print(f"✅ 技能体系完成: {len(skills)}个技能")
            
            # 第六步：在同一对话中逐个生成场景
            print(f"🎬 开始在统一上下文中创作 {total_scenes} 个场景...")
            script_nodes = await self.generate_detailed_plot(task_id, story_structure, characters, theater_data)
            print(f"✅ 剧情创作完成: {len(script_nodes)}个节点")
            
            # 第七步：最终优化
            result = await self.finalize_generation(task_id, theater_data, script_nodes, characters, skills)
            
            # 标记任务完成
            generation_tasks[task_id].status = TaskStatus.COMPLETED
            generation_tasks[task_id].result = result
            generation_tasks[task_id].progress = 100
            generation_tasks[task_id].current_stage = GenerationStage.COMPLETE
            generation_tasks[task_id].message = "智能生成完成！"
            
            print(f"🎉 任务 {task_id} 生成完成!")
            print(f"📊 生成统计: {len(script_nodes)}个场景, {len(characters)}个角色, {len(skills)}个技能")
            
        except Exception as e:
            error_msg = f"生成失败: {str(e)}"
            print(f"❌ 任务 {task_id} {error_msg}")
            
            # 标记任务失败
            generation_tasks[task_id].status = TaskStatus.FAILED
            generation_tasks[task_id].error = str(e)
            generation_tasks[task_id].message = error_msg
        
        finally:
            # 清理对话历史以节省内存
            if task_id in self.conversation_histories:
                del self.conversation_histories[task_id]

    def _get_stage_progress_breakdown(self, current_stage: GenerationStage, overall_progress: float) -> Dict:
        """获取各阶段进度分解"""
        stages = [
            {"stage": GenerationStage.ANALYSIS, "range": (0, 10)},
            {"stage": GenerationStage.CONCEPT, "range": (10, 25)},
            {"stage": GenerationStage.STRUCTURE, "range": (25, 40)},
            {"stage": GenerationStage.CHARACTERS, "range": (40, 55)},
            {"stage": GenerationStage.SKILLS, "range": (55, 70)},
            {"stage": GenerationStage.PLOT, "range": (70, 95)},
            {"stage": GenerationStage.OPTIMIZATION, "range": (95, 100)},
        ]
        
        breakdown = {}
        for stage_info in stages:
            stage = stage_info["stage"]
            start, end = stage_info["range"]
            
            if overall_progress <= start:
                breakdown[stage.value] = 0
            elif overall_progress >= end:
                breakdown[stage.value] = 100
            elif stage == current_stage:
                breakdown[stage.value] = ((overall_progress - start) / (end - start)) * 100
            else:
                breakdown[stage.value] = 0 if overall_progress < start else 100
        
        return breakdown

# ==================== FastAPI应用 ====================

app = FastAPI(
    title="智能剧场生成器",
    description="AI驱动的智能剧场创作工具",
    version="2.3.0",
    docs_url="/docs",
    redoc_url="/redoc"
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 初始化生成器
try:
    generator = IntelligentTheaterGenerator()
    print("✅ 智能生成器初始化成功")
except Exception as e:
    print(f"❌ 智能生成器初始化失败: {e}")
    generator = None

# ==================== API端点 ====================

@app.get("/", response_model=ApiResponse)
async def root():
    return ApiResponse(
        success=True,
        message="智能剧场生成器服务正在运行",
        data={
            "version": "2.3.0", 
            "docs": "/docs",
            "features": ["intelligent_generation", "progress_tracking", "context_continuity", "skills_normalization"],
            "status": "ready" if generator else "generator_not_ready"
        }
    )

@app.get("/health", response_model=ApiResponse)
async def health_check():
    try:
        api_key = os.getenv('GEEKAI_API_KEY')
        if not api_key:
            return ApiResponse(
                success=False,
                message="API密钥未配置",
                error_code="CONFIG_ERROR"
            )
        
        if not generator:
            return ApiResponse(
                success=False,
                message="生成器未正确初始化",
                error_code="GENERATOR_ERROR"
            )
        
        return ApiResponse(
            success=True,
            message="服务正常运行",
            data={
                "status": "healthy", 
                "timestamp": datetime.now().isoformat(),
                "generator_ready": True,
                "active_tasks": len([t for t in generation_tasks.values() if t.status == TaskStatus.RUNNING]),
                "conversation_contexts": len(generator.conversation_histories)
            }
        )
    except Exception as e:
        return ApiResponse(
            success=False,
            message=f"健康检查失败: {str(e)}",
            error_code="HEALTH_CHECK_FAILED"
        )

@app.post("/generate/intelligent", response_model=ApiResponse)
async def start_intelligent_generation(request: IntelligentGenerationRequest, background_tasks: BackgroundTasks):
    """启动智能生成任务"""
    try:
        if not generator:
            raise HTTPException(
                status_code=500,
                detail="生成器未初始化，请检查API密钥配置"
            )
        
        # 创建任务ID
        task_id = str(uuid.uuid4())
        
        # 初始化任务进度
        generation_tasks[task_id] = GenerationProgress(
            task_id=task_id,
            status=TaskStatus.PENDING,
            progress=0,
            current_stage=GenerationStage.ANALYSIS,
            message="任务已创建，准备开始生成...",
            created_at=datetime.now()
        )
        
        # 在后台启动生成任务
        background_tasks.add_task(generator.generate_intelligent_theater, task_id, request)
        
        print(f"🚀 启动智能生成任务: {task_id}")
        
        return ApiResponse(
            success=True,
            message="智能生成任务已启动",
            task_id=task_id,
            data={
                "task_id": task_id,
                "estimated_duration": "3-8分钟",
                "status": "started"
            }
        )
    
    except Exception as e:
        print(f"❌ 启动生成任务失败: {e}")
        raise HTTPException(
            status_code=500,
            detail={
                "success": False,
                "message": f"启动生成任务失败: {str(e)}",
                "error_code": "TASK_START_FAILED"
            }
        )

@app.get("/database/theaters", response_model=ApiResponse)
async def get_theaters_list(limit: int = 20, offset: int = 0):
    """获取剧场列表"""
    try:
        if not generator or not generator.mysql_manager:
            raise HTTPException(status_code=500, detail="数据库管理器未初始化")
        
        result = generator.mysql_manager.get_theaters_list(limit=limit, offset=offset)
        
        return ApiResponse(
            success=result.get('success', True),
            message="获取剧场列表成功",
            data=result
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取剧场列表失败: {str(e)}")

@app.get("/database/theaters/{theater_id}", response_model=ApiResponse)
async def get_theater_detail(theater_id: int):
    """获取剧场详细信息"""
    try:
        if not generator or not generator.mysql_manager:
            raise HTTPException(status_code=500, detail="数据库管理器未初始化")
        
        theater_data = generator.mysql_manager.get_theater_by_id(theater_id)
        
        if not theater_data:
            raise HTTPException(status_code=404, detail="剧场不存在")
        
        return ApiResponse(
            success=True,
            message="获取剧场详情成功",
            data=theater_data
        )
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取剧场详情失败: {str(e)}")

@app.delete("/database/theaters/{theater_id}", response_model=ApiResponse)
async def delete_theater(theater_id: int):
    """删除剧场"""
    try:
        if not generator or not generator.mysql_manager:
            raise HTTPException(status_code=500, detail="数据库管理器未初始化")
        
        result = generator.mysql_manager.delete_theater(theater_id)
        
        return ApiResponse(
            success=result.get('success', False),
            message=result.get('message', '删除操作完成'),
            data={"theater_id": theater_id} if result.get('success') else None,
            error_code="DELETE_FAILED" if not result.get('success') else None
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"删除剧场失败: {str(e)}")

@app.get("/database/logs", response_model=ApiResponse)
async def get_generation_logs(task_id: str = None, limit: int = 50):
    """获取生成日志"""
    try:
        if not generator or not generator.mysql_manager:
            raise HTTPException(status_code=500, detail="数据库管理器未初始化")
        
        logs = generator.mysql_manager.get_generation_logs(task_id=task_id, limit=limit)
        
        return ApiResponse(
            success=True,
            message="获取日志成功",
            data={
                "logs": logs,
                "total": len(logs),
                "task_id": task_id,
                "limit": limit
            }
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取日志失败: {str(e)}")

@app.get("/database/test", response_model=ApiResponse)
async def test_database_connection():
    """测试数据库连接"""
    try:
        if not generator or not generator.mysql_manager:
            return ApiResponse(
                success=False,
                message="数据库管理器未初始化",
                error_code="MANAGER_NOT_READY"
            )
        
        # 测试连接
        with generator.mysql_manager.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute("SELECT VERSION() as version, NOW() as current_time")
            result = cursor.fetchone()
            cursor.close()
        
        # 获取数据库统计
        stats = generator.mysql_manager.get_theaters_list(limit=1)
        
        return ApiResponse(
            success=True,
            message="数据库连接正常",
            data={
                "mysql_version": result[0] if result else "Unknown",
                "current_time": result[1].isoformat() if result and len(result) > 1 else None,
                "total_theaters": stats.get('total', 0),
                "database": generator.mysql_manager.config['database'],
                "host": generator.mysql_manager.config['host']
            }
        )
    except Exception as e:
        return ApiResponse(
            success=False,
            message=f"数据库连接测试失败: {str(e)}",
            error_code="CONNECTION_FAILED"
        )
@app.get("/generate/progress/{task_id}", response_model=ApiResponse)
async def get_generation_progress(task_id: str):
    """获取生成进度"""
    if task_id not in generation_tasks:
        raise HTTPException(
            status_code=404,
            detail={
                "success": False,
                "message": "任务不存在",
                "error_code": "TASK_NOT_FOUND"
            }
        )
    
    task = generation_tasks[task_id]
    
    return ApiResponse(
        success=True,
        message="获取进度成功",
        data={
            "task_id": task_id,
            "status": task.status.value,
            "progress": task.progress,
            "current_stage": task.current_stage.value,
            "message": task.message,
            "result": task.result if task.status == TaskStatus.COMPLETED else None,
            "error": task.error if task.status == TaskStatus.FAILED else None,
            "created_at": task.created_at.isoformat() if task.created_at else None
        }
    )
@app.post("/debug/validate-characters", response_model=ApiResponse)
async def validate_characters_data(characters_data: List[dict]):
    """验证角色数据格式"""
    validation_results = []
    
    for i, char in enumerate(characters_data):
        result = {
            "index": i,
            "valid": True,
            "issues": [],
            "data": char
        }
        
        # 检查必需字段
        required_fields = ['id', 'name', 'description', 'avatar', 'selectedSkills']
        for field in required_fields:
            if field not in char:
                result["valid"] = False
                result["issues"].append(f"缺少字段: {field}")
        
        # 检查字段类型
        if 'selectedSkills' in char and not isinstance(char['selectedSkills'], list):
            result["valid"] = False
            result["issues"].append(f"selectedSkills 应该是列表，当前是: {type(char['selectedSkills'])}")
        
        validation_results.append(result)
    
    return ApiResponse(
        success=True,
        message="角色数据验证完成",
        data={
            "total": len(characters_data),
            "valid": len([r for r in validation_results if r["valid"]]),
            "invalid": len([r for r in validation_results if not r["valid"]]),
            "results": validation_results
        }
    )

@app.get("/generate/progress/{task_id}/detailed", response_model=ApiResponse)
async def get_detailed_generation_progress(task_id: str):
    """获取详细的生成进度信息"""
    if task_id not in generation_tasks:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    task = generation_tasks[task_id]
    
    # 计算预估剩余时间
    if task.progress > 0 and task.status == TaskStatus.RUNNING:
        elapsed_time = (datetime.now() - task.created_at).total_seconds() if task.created_at else 0
        estimated_total_time = elapsed_time / (task.progress / 100) if task.progress > 0 else 0
        estimated_remaining_time = max(0, estimated_total_time - elapsed_time)
    else:
        estimated_remaining_time = 0
    
    # 构建阶段信息
    stage_info = {
        GenerationStage.ANALYSIS: {"name": "需求分析", "icon": "📊"},
        GenerationStage.CONCEPT: {"name": "概念构建", "icon": "💡"},
        GenerationStage.STRUCTURE: {"name": "故事架构", "icon": "🏗️"},
        GenerationStage.CHARACTERS: {"name": "角色设计", "icon": "👥"},
        GenerationStage.SKILLS: {"name": "技能体系", "icon": "⚔️"},
        GenerationStage.PLOT: {"name": "剧情生成", "icon": "📖"},
        GenerationStage.OPTIMIZATION: {"name": "整体优化", "icon": "✨"},
        GenerationStage.COMPLETE: {"name": "生成完成", "icon": "✅"},
    }
    
    return ApiResponse(
        success=True,
        message="获取详细进度成功",
        data={
            "task_id": task_id,
            "status": task.status.value,
            "progress": round(task.progress, 2),
            "current_stage": {
                "key": task.current_stage.value,
                "name": stage_info.get(task.current_stage, {}).get("name", "未知阶段"),
                "icon": stage_info.get(task.current_stage, {}).get("icon", "⚙️")
            },
            "message": task.message,
            "estimated_remaining_seconds": round(estimated_remaining_time),
            "result": task.result if task.status == TaskStatus.COMPLETED else None,
            "error": task.error if task.status == TaskStatus.FAILED else None,
            "created_at": task.created_at.isoformat() if task.created_at else None,
            "stage_progress": generator._get_stage_progress_breakdown(task.current_stage, task.progress) if generator else {}
        }
    )

@app.get("/generate/tasks", response_model=ApiResponse)
async def list_generation_tasks():
    """获取所有生成任务"""
    tasks_info = []
    for task_id, task in generation_tasks.items():
        tasks_info.append({
            "task_id": task_id,
            "status": task.status.value,
            "progress": task.progress,
            "current_stage": task.current_stage.value,
            "created_at": task.created_at.isoformat() if task.created_at else None
        })
    
    return ApiResponse(
        success=True,
        message="获取任务列表成功",
        data={
            "tasks": tasks_info,
            "total": len(tasks_info),
            "active": len([t for t in generation_tasks.values() if t.status == TaskStatus.RUNNING])
        }
    )

@app.delete("/generate/task/{task_id}", response_model=ApiResponse)
async def cancel_generation_task(task_id: str):
    """取消生成任务"""
    if task_id not in generation_tasks:
        raise HTTPException(
            status_code=404,
            detail="任务不存在"
        )
    
    task = generation_tasks[task_id]
    if task.status in [TaskStatus.COMPLETED, TaskStatus.FAILED]:
        return ApiResponse(
            success=False,
            message="任务已完成或失败，无法取消",
            error_code="TASK_CANNOT_CANCEL"
        )
    
    # 标记为失败状态（简单的取消方式）
    task.status = TaskStatus.FAILED
    task.error = "用户取消"
    task.message = "任务已被用户取消"
    
    # 清理对话历史
    if generator and task_id in generator.conversation_histories:
        del generator.conversation_histories[task_id]
    
    return ApiResponse(
        success=True,
        message="任务已取消"
    )

# ==================== 异常处理 ====================

@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
    """HTTP异常处理"""
    return JSONResponse(
        status_code=exc.status_code,
        content=exc.detail if isinstance(exc.detail, dict) else {"message": str(exc.detail)}
    )

@app.exception_handler(Exception)
async def general_exception_handler(request, exc):
    """通用异常处理"""
    print(f"❌ 服务器错误: {exc}")
    return JSONResponse(
        status_code=500,
        content={
            "success": False,
            "message": f"服务器内部错误: {str(exc)}",
            "error_code": "INTERNAL_SERVER_ERROR"
        }
    )

# ==================== 启动配置 ====================

def main():
    """主函数"""
    if not os.getenv('GEEKAI_API_KEY'):
        print("⚠️  请设置GEEKAI_API_KEY环境变量")
        print("   例如: export GEEKAI_API_KEY='your-api-key'")
        print("   或者: set GEEKAI_API_KEY=your-api-key (Windows)")
        return False
    
    print("🧠 启动智能剧场生成器API服务...")
    print(f"📖 API文档: http://localhost:8000/docs")
    print(f"🔍 Redoc文档: http://localhost:8000/redoc")
    print("💡 按 Ctrl+C 停止服务")
    print()
    print("🚀 支持的功能:")
    print("   - 智能生成向导")
    print("   - 单一对话上下文")
    print("   - 实时进度跟踪")
    print("   - 逐个场景生成")
    print("   - 内容一致性保证")
    print("   - 🔧 技能数据标准化处理")
    
    return True

if __name__ == "__main__":
    if main():
        uvicorn.run(
            "ai:app",
            host="0.0.0.0",
            port=8000,
            reload=True,
            log_level="info",
            access_log=True
        )
